package org.dfl.plugin.views.palette;

import org.apache.log4j.Logger;
import org.dfl.core.utils.Utils;
import org.dfl.messages.Messages;
import org.dfl.plugin.views.palette.model.FolderPaletteEntry;
import org.dfl.plugin.views.palette.model.PaletteEntry;
import org.dfl.plugin.views.palette.model.TransitionPaletteEntry;
import org.dfl.taverna.ProcessorLoadListener;
import org.dfl.taverna.ProcessorTreeNode;
import org.dfl.taverna.Taverna;
import org.dfl.taverna.TavernaProcessor;

/**
 * class that loads transition palette tree
 * 
 * @author Piotr Wlodarczyk
 * 
 */
public class TavernaTreeLoader implements ProcessorLoadListener {
	private static Logger logger = Logger.getLogger(TavernaTreeLoader.class);
	private PaletteEntry root = new FolderPaletteEntry(Messages.TavernaTreeLoader_0);
	
	private static TavernaTreeLoader instance;
	private TavernaTreeLoader object = this;
	
	public static TavernaTreeLoader getInstance(){
		if(instance == null){
			instance = new TavernaTreeLoader();
		}
	    
		return instance;
	}
	
	public void run(){
		new Thread() {
			public void run() {
				PaletteView.addTreeElement(root);
				Taverna.getInstance().loadProcessors(object);
			}
		}.start();
	}
	
	private void addMappedTavernaTree(ProcessorTreeNode node) {
		final PaletteEntry entry = getTree(node);
		if(entry != null){
			Utils.execSynch(new Runnable() {
				 public void run() {
					 try{
						 root.addChild(entry);
					 }catch(Throwable e){
						 logger.error(e);
					 }
				 }
				});
		}
	}
	
	private synchronized PaletteEntry getTree(ProcessorTreeNode root) {
		if (root == null) {
			return null;
		}
		
		int rootCount = root.getChildrenCount();
		TavernaProcessor processor = root.getProcessor();
		
		if (rootCount == 0 && processor != null) {
			return new TransitionPaletteEntry(processor.getFactory(), processor.getIcon());
		} else if (rootCount > 0) {
			PaletteEntry entry = new FolderPaletteEntry(root.getLabel());
			PaletteEntry sub = null;
			ProcessorTreeNode child = null;
			
			for (int i = 0; i < rootCount; ++i) {
				child = root.getChildNode(i);
				sub = getTree(child);
				
				if (sub != null) {
					entry.addChild(sub);
				}
			}
			
			return entry;
		} else {
			return null;
		}
	}

	public void processorSubtreeLoaded(Object sender, ProcessorTreeNode tree) {
		addMappedTavernaTree(tree);
	}
}
